<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>尝鲜 Svelte 前端框架，开发读书笔记 | 鱼皮的编程宝典</title>
    <meta name="generator" content="VuePress 1.9.10">
    <link rel="icon" href="/favicon.ico">
    <script>
        var _hmt = _hmt || [];
        (function() {
          var hm = document.createElement("script");
          hm.src = "https://hm.baidu.com/hm.js?2675818a983a3131404cee835018f016";
          var s = document.getElementsByTagName("script")[0]; 
          s.parentNode.insertBefore(hm, s);
        })();
      </script>
    <meta name="description" content="贴心的编程学习路线，全面的编程知识百科">
    <meta property="article:modified_time" content="2023-11-11T12:17:47.000Z">
    <meta property="og:site_name" content="鱼皮的编程宝典">
    <meta property="og:title" content="尝鲜 Svelte 前端框架，开发读书笔记">
    <meta property="og:type" content="article">
    <meta property="og:url" content="https://codefather.cn/%E5%B0%9D%E9%B2%9C-svelte-%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6-%E5%BC%80%E5%8F%91%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/">
    <meta name="twitter:title" content="尝鲜 Svelte 前端框架，开发读书笔记">
    <meta name="twitter:url" content="https://codefather.cn/%E5%B0%9D%E9%B2%9C-svelte-%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6-%E5%BC%80%E5%8F%91%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:label1" content="Written by">
    <meta name="twitter:label2" content="Filed under">
    <meta name="twitter:data2" content="程序员, 编程, 计算机">
    <meta property="article:tag" content="程序员">
    <meta name="keywords" content="程序员鱼皮, 编程学习路线, 编程知识百科, Java, 编程导航, 前端, 开发, 编程分享, 项目, IT, 求职, 面经">
    
    <link rel="preload" href="/assets/css/0.styles.40c15e22.css" as="style"><link rel="preload" href="/assets/js/app.12ab4756.js" as="script"><link rel="preload" href="/assets/js/2.fd06b53e.js" as="script"><link rel="preload" href="/assets/js/200.52f08765.js" as="script"><link rel="prefetch" href="/assets/js/1.17ea1209.js"><link rel="prefetch" href="/assets/js/10.d9532d8f.js"><link rel="prefetch" href="/assets/js/100.064ea126.js"><link rel="prefetch" href="/assets/js/101.d64c5b33.js"><link rel="prefetch" href="/assets/js/102.5e29a62c.js"><link rel="prefetch" href="/assets/js/103.59ad6cd7.js"><link rel="prefetch" href="/assets/js/104.ae4763e8.js"><link rel="prefetch" href="/assets/js/105.2a9124be.js"><link rel="prefetch" href="/assets/js/106.529bca07.js"><link rel="prefetch" href="/assets/js/107.c8671a0d.js"><link rel="prefetch" href="/assets/js/108.55c93c64.js"><link rel="prefetch" href="/assets/js/109.7d1efa54.js"><link rel="prefetch" href="/assets/js/11.2f89b5eb.js"><link rel="prefetch" href="/assets/js/110.0caecbf5.js"><link rel="prefetch" href="/assets/js/111.a2aeae49.js"><link rel="prefetch" href="/assets/js/112.eb7ceda5.js"><link rel="prefetch" href="/assets/js/113.f304408d.js"><link rel="prefetch" href="/assets/js/114.988c637f.js"><link rel="prefetch" href="/assets/js/115.bfdeed31.js"><link rel="prefetch" href="/assets/js/116.a47b8c53.js"><link rel="prefetch" href="/assets/js/117.2e1e8250.js"><link rel="prefetch" href="/assets/js/118.758ce408.js"><link rel="prefetch" href="/assets/js/119.73d9e688.js"><link rel="prefetch" href="/assets/js/12.53aaa509.js"><link rel="prefetch" href="/assets/js/120.202a8b2e.js"><link rel="prefetch" href="/assets/js/121.ca91d59a.js"><link rel="prefetch" href="/assets/js/122.8804c0dd.js"><link rel="prefetch" href="/assets/js/123.ceada225.js"><link rel="prefetch" href="/assets/js/124.4b2718b7.js"><link rel="prefetch" href="/assets/js/125.72134235.js"><link rel="prefetch" href="/assets/js/126.167b162c.js"><link rel="prefetch" href="/assets/js/127.f8139c17.js"><link rel="prefetch" href="/assets/js/128.da64a377.js"><link rel="prefetch" href="/assets/js/129.c07963b1.js"><link rel="prefetch" href="/assets/js/13.52940164.js"><link rel="prefetch" href="/assets/js/130.f66fc8bb.js"><link rel="prefetch" href="/assets/js/131.a913c7dd.js"><link rel="prefetch" href="/assets/js/132.ea648654.js"><link rel="prefetch" href="/assets/js/133.074ca70e.js"><link rel="prefetch" href="/assets/js/134.dc79ddd8.js"><link rel="prefetch" href="/assets/js/135.c4516208.js"><link rel="prefetch" href="/assets/js/136.2546baf7.js"><link rel="prefetch" href="/assets/js/137.56454fc6.js"><link rel="prefetch" href="/assets/js/138.bdb002bf.js"><link rel="prefetch" href="/assets/js/139.40a2f9b5.js"><link rel="prefetch" href="/assets/js/14.ade1e74d.js"><link rel="prefetch" href="/assets/js/140.06b20427.js"><link rel="prefetch" href="/assets/js/141.8dd992e3.js"><link rel="prefetch" href="/assets/js/142.d9305485.js"><link rel="prefetch" href="/assets/js/143.41bf907e.js"><link rel="prefetch" href="/assets/js/144.c138960c.js"><link rel="prefetch" href="/assets/js/145.fc5b38c8.js"><link rel="prefetch" href="/assets/js/146.c9166b70.js"><link rel="prefetch" href="/assets/js/147.c31d8a01.js"><link rel="prefetch" href="/assets/js/148.5c0534ca.js"><link rel="prefetch" href="/assets/js/149.d2355ea2.js"><link rel="prefetch" href="/assets/js/15.970a8ca5.js"><link rel="prefetch" href="/assets/js/150.c1644898.js"><link rel="prefetch" href="/assets/js/151.b6e4adf0.js"><link rel="prefetch" href="/assets/js/152.7a5071aa.js"><link rel="prefetch" href="/assets/js/153.31abbc68.js"><link rel="prefetch" href="/assets/js/154.9c6bb079.js"><link rel="prefetch" href="/assets/js/155.e5506a40.js"><link rel="prefetch" href="/assets/js/156.992dab50.js"><link rel="prefetch" href="/assets/js/157.12a6ee84.js"><link rel="prefetch" href="/assets/js/158.84dc1045.js"><link rel="prefetch" href="/assets/js/159.fd2022b1.js"><link rel="prefetch" href="/assets/js/16.ff971500.js"><link rel="prefetch" href="/assets/js/160.8d8889cd.js"><link rel="prefetch" href="/assets/js/161.31797def.js"><link rel="prefetch" href="/assets/js/162.bfae7a75.js"><link rel="prefetch" href="/assets/js/163.e5e8094d.js"><link rel="prefetch" href="/assets/js/164.870f212c.js"><link rel="prefetch" href="/assets/js/165.8da20a31.js"><link rel="prefetch" href="/assets/js/166.950a187d.js"><link rel="prefetch" href="/assets/js/167.fd042c52.js"><link rel="prefetch" href="/assets/js/168.7d9f058d.js"><link rel="prefetch" href="/assets/js/169.205df80e.js"><link rel="prefetch" href="/assets/js/17.4b045b26.js"><link rel="prefetch" href="/assets/js/170.270108a3.js"><link rel="prefetch" href="/assets/js/171.9f03d27d.js"><link rel="prefetch" href="/assets/js/172.1882bac7.js"><link rel="prefetch" href="/assets/js/173.fc1fe7d4.js"><link rel="prefetch" href="/assets/js/174.d77c927b.js"><link rel="prefetch" href="/assets/js/175.019b9e83.js"><link rel="prefetch" href="/assets/js/176.5ce31bd8.js"><link rel="prefetch" href="/assets/js/177.9a2006f2.js"><link rel="prefetch" href="/assets/js/178.88265ac1.js"><link rel="prefetch" href="/assets/js/179.3205ce07.js"><link rel="prefetch" href="/assets/js/18.1cdd0514.js"><link rel="prefetch" href="/assets/js/180.2ff51f44.js"><link rel="prefetch" href="/assets/js/181.f792ce97.js"><link rel="prefetch" href="/assets/js/182.103328e1.js"><link rel="prefetch" href="/assets/js/183.40fde303.js"><link rel="prefetch" href="/assets/js/184.1f36ac78.js"><link rel="prefetch" href="/assets/js/185.cf3b1c00.js"><link rel="prefetch" href="/assets/js/186.f7981399.js"><link rel="prefetch" href="/assets/js/187.20fe296d.js"><link rel="prefetch" href="/assets/js/188.7b004fea.js"><link rel="prefetch" href="/assets/js/189.599ca2d9.js"><link rel="prefetch" href="/assets/js/19.5740e4d6.js"><link rel="prefetch" href="/assets/js/190.14087c07.js"><link rel="prefetch" href="/assets/js/191.b0f73f6d.js"><link rel="prefetch" href="/assets/js/192.9d171669.js"><link rel="prefetch" href="/assets/js/193.00975585.js"><link rel="prefetch" href="/assets/js/194.2c7c43b4.js"><link rel="prefetch" href="/assets/js/195.ff126254.js"><link rel="prefetch" href="/assets/js/196.6546ae1c.js"><link rel="prefetch" href="/assets/js/197.eedb67bb.js"><link rel="prefetch" href="/assets/js/198.acdcc22c.js"><link rel="prefetch" href="/assets/js/199.7993a6b2.js"><link rel="prefetch" href="/assets/js/20.8885a4fa.js"><link rel="prefetch" href="/assets/js/201.b85ab10b.js"><link rel="prefetch" href="/assets/js/202.ccec1c85.js"><link rel="prefetch" href="/assets/js/203.3f50a6ed.js"><link rel="prefetch" href="/assets/js/204.f28b803b.js"><link rel="prefetch" href="/assets/js/205.c51c53fd.js"><link rel="prefetch" href="/assets/js/206.ba0aa8f6.js"><link rel="prefetch" href="/assets/js/207.0dce311a.js"><link rel="prefetch" href="/assets/js/208.0ea629a6.js"><link rel="prefetch" href="/assets/js/209.f48c3e71.js"><link rel="prefetch" href="/assets/js/21.0bb62db4.js"><link rel="prefetch" href="/assets/js/210.689db8f2.js"><link rel="prefetch" href="/assets/js/211.72bc0f1f.js"><link rel="prefetch" href="/assets/js/212.456135bd.js"><link rel="prefetch" href="/assets/js/213.d0ea50fc.js"><link rel="prefetch" href="/assets/js/214.1400da91.js"><link rel="prefetch" href="/assets/js/215.aeef3e5d.js"><link rel="prefetch" href="/assets/js/216.a60215af.js"><link rel="prefetch" href="/assets/js/217.d6cd8b69.js"><link rel="prefetch" href="/assets/js/218.1bd500fc.js"><link rel="prefetch" href="/assets/js/219.20faf611.js"><link rel="prefetch" href="/assets/js/22.3e8347a6.js"><link rel="prefetch" href="/assets/js/220.6714179b.js"><link rel="prefetch" href="/assets/js/221.fb5b643d.js"><link rel="prefetch" href="/assets/js/222.d96272e5.js"><link rel="prefetch" href="/assets/js/223.4cb7dc3d.js"><link rel="prefetch" href="/assets/js/224.500d94cc.js"><link rel="prefetch" href="/assets/js/225.d006c34e.js"><link rel="prefetch" href="/assets/js/226.73612150.js"><link rel="prefetch" href="/assets/js/227.b02db9d1.js"><link rel="prefetch" href="/assets/js/228.aad43ff2.js"><link rel="prefetch" href="/assets/js/229.65340802.js"><link rel="prefetch" href="/assets/js/23.ceb5a5ff.js"><link rel="prefetch" href="/assets/js/230.97cab104.js"><link rel="prefetch" href="/assets/js/231.8415349a.js"><link rel="prefetch" href="/assets/js/232.db6d2697.js"><link rel="prefetch" href="/assets/js/233.723d05b1.js"><link rel="prefetch" href="/assets/js/234.26ed5e94.js"><link rel="prefetch" href="/assets/js/235.a586122b.js"><link rel="prefetch" href="/assets/js/236.f802bda8.js"><link rel="prefetch" href="/assets/js/237.cc8767ad.js"><link rel="prefetch" href="/assets/js/238.6485459e.js"><link rel="prefetch" href="/assets/js/239.9fbf3a55.js"><link rel="prefetch" href="/assets/js/24.07267ac6.js"><link rel="prefetch" href="/assets/js/240.1188f244.js"><link rel="prefetch" href="/assets/js/241.cbfb154d.js"><link rel="prefetch" href="/assets/js/242.352cea5a.js"><link rel="prefetch" href="/assets/js/243.07947e1c.js"><link rel="prefetch" href="/assets/js/244.f5b26fa9.js"><link rel="prefetch" href="/assets/js/245.c6030e32.js"><link rel="prefetch" href="/assets/js/246.d3fe99f7.js"><link rel="prefetch" href="/assets/js/247.185ae95d.js"><link rel="prefetch" href="/assets/js/248.a5f1548c.js"><link rel="prefetch" href="/assets/js/249.19691113.js"><link rel="prefetch" href="/assets/js/25.15e1f641.js"><link rel="prefetch" href="/assets/js/250.72fa1d33.js"><link rel="prefetch" href="/assets/js/251.bedd56f7.js"><link rel="prefetch" href="/assets/js/252.32bbcc8b.js"><link rel="prefetch" href="/assets/js/253.b59e5846.js"><link rel="prefetch" href="/assets/js/254.c0e37e1a.js"><link rel="prefetch" href="/assets/js/255.850da3cc.js"><link rel="prefetch" href="/assets/js/256.952d9817.js"><link rel="prefetch" href="/assets/js/257.88667bb8.js"><link rel="prefetch" href="/assets/js/258.c5873c28.js"><link rel="prefetch" href="/assets/js/259.6ae1dcbc.js"><link rel="prefetch" href="/assets/js/26.35b2bbdc.js"><link rel="prefetch" href="/assets/js/260.cb940cc3.js"><link rel="prefetch" href="/assets/js/261.0686c3e9.js"><link rel="prefetch" href="/assets/js/262.d0719839.js"><link rel="prefetch" href="/assets/js/263.ae83ebc1.js"><link rel="prefetch" href="/assets/js/264.209ad8a3.js"><link rel="prefetch" href="/assets/js/265.be8d1ee8.js"><link rel="prefetch" href="/assets/js/266.c51bceaa.js"><link rel="prefetch" href="/assets/js/267.fe8af48a.js"><link rel="prefetch" href="/assets/js/268.e18ed861.js"><link rel="prefetch" href="/assets/js/269.7126031e.js"><link rel="prefetch" href="/assets/js/27.270fcb06.js"><link rel="prefetch" href="/assets/js/270.89ead106.js"><link rel="prefetch" href="/assets/js/271.0643d07a.js"><link rel="prefetch" href="/assets/js/272.32a8e4b0.js"><link rel="prefetch" href="/assets/js/273.9881da47.js"><link rel="prefetch" href="/assets/js/274.2de022ea.js"><link rel="prefetch" href="/assets/js/275.d9a4fe99.js"><link rel="prefetch" href="/assets/js/276.d33de2e9.js"><link rel="prefetch" href="/assets/js/277.1ec367ab.js"><link rel="prefetch" href="/assets/js/278.66ab7c11.js"><link rel="prefetch" href="/assets/js/279.ff51cd15.js"><link rel="prefetch" href="/assets/js/28.ef3f6db2.js"><link rel="prefetch" href="/assets/js/280.ef45ed5f.js"><link rel="prefetch" href="/assets/js/281.87f26b81.js"><link rel="prefetch" href="/assets/js/282.c8ef594b.js"><link rel="prefetch" href="/assets/js/283.15643091.js"><link rel="prefetch" href="/assets/js/284.c4f25b2e.js"><link rel="prefetch" href="/assets/js/285.2d16e4b6.js"><link rel="prefetch" href="/assets/js/286.44eba266.js"><link rel="prefetch" href="/assets/js/287.7613e62f.js"><link rel="prefetch" href="/assets/js/288.b9546d55.js"><link rel="prefetch" href="/assets/js/289.125f85d8.js"><link rel="prefetch" href="/assets/js/29.177558be.js"><link rel="prefetch" href="/assets/js/290.db375797.js"><link rel="prefetch" href="/assets/js/291.90946626.js"><link rel="prefetch" href="/assets/js/292.a4524678.js"><link rel="prefetch" href="/assets/js/293.3ed9b083.js"><link rel="prefetch" href="/assets/js/294.d6c14116.js"><link rel="prefetch" href="/assets/js/295.2b485032.js"><link rel="prefetch" href="/assets/js/296.29d9aa0f.js"><link rel="prefetch" href="/assets/js/297.bfd72435.js"><link rel="prefetch" href="/assets/js/298.fc056989.js"><link rel="prefetch" href="/assets/js/299.0a3f258e.js"><link rel="prefetch" href="/assets/js/3.4dc033c7.js"><link rel="prefetch" href="/assets/js/30.248a229d.js"><link rel="prefetch" href="/assets/js/300.d064d776.js"><link rel="prefetch" href="/assets/js/301.d95b9fc0.js"><link rel="prefetch" href="/assets/js/302.1afa637a.js"><link rel="prefetch" href="/assets/js/303.231beaa8.js"><link rel="prefetch" href="/assets/js/304.05df35d9.js"><link rel="prefetch" href="/assets/js/305.f2d83cf9.js"><link rel="prefetch" href="/assets/js/306.d54f5e5e.js"><link rel="prefetch" href="/assets/js/307.d5df9000.js"><link rel="prefetch" href="/assets/js/308.ef2f52b3.js"><link rel="prefetch" href="/assets/js/309.d1f13319.js"><link rel="prefetch" href="/assets/js/31.32a62b91.js"><link rel="prefetch" href="/assets/js/310.30b84be3.js"><link rel="prefetch" href="/assets/js/311.d79e3145.js"><link rel="prefetch" href="/assets/js/312.58e24f19.js"><link rel="prefetch" href="/assets/js/313.9809a122.js"><link rel="prefetch" href="/assets/js/314.e92e41b1.js"><link rel="prefetch" href="/assets/js/315.8c2fc1d4.js"><link rel="prefetch" href="/assets/js/316.a0904343.js"><link rel="prefetch" href="/assets/js/317.18e42b54.js"><link rel="prefetch" href="/assets/js/318.6b051d27.js"><link rel="prefetch" href="/assets/js/319.513b0197.js"><link rel="prefetch" href="/assets/js/32.23b75afc.js"><link rel="prefetch" href="/assets/js/320.ae91bc36.js"><link rel="prefetch" href="/assets/js/321.a194efea.js"><link rel="prefetch" href="/assets/js/322.8273020e.js"><link rel="prefetch" href="/assets/js/323.d332e08f.js"><link rel="prefetch" href="/assets/js/324.ed867b64.js"><link rel="prefetch" href="/assets/js/325.c43ccf9a.js"><link rel="prefetch" href="/assets/js/326.9497d879.js"><link rel="prefetch" href="/assets/js/327.7f095e40.js"><link rel="prefetch" href="/assets/js/328.cb5c5847.js"><link rel="prefetch" href="/assets/js/329.d36b59f3.js"><link rel="prefetch" href="/assets/js/33.b258b779.js"><link rel="prefetch" href="/assets/js/330.b1a092b9.js"><link rel="prefetch" href="/assets/js/331.ff86566f.js"><link rel="prefetch" href="/assets/js/332.0daafa9f.js"><link rel="prefetch" href="/assets/js/333.b7e50524.js"><link rel="prefetch" href="/assets/js/334.7dcf9f0b.js"><link rel="prefetch" href="/assets/js/335.862c410a.js"><link rel="prefetch" href="/assets/js/336.c6384990.js"><link rel="prefetch" href="/assets/js/337.ab9d5e52.js"><link rel="prefetch" href="/assets/js/338.598ae59e.js"><link rel="prefetch" href="/assets/js/339.9b810ff8.js"><link rel="prefetch" href="/assets/js/34.3bd60f1f.js"><link rel="prefetch" href="/assets/js/340.5609a53c.js"><link rel="prefetch" href="/assets/js/341.969d335a.js"><link rel="prefetch" href="/assets/js/342.43f85dba.js"><link rel="prefetch" href="/assets/js/343.47280ef9.js"><link rel="prefetch" href="/assets/js/344.346ae5fc.js"><link rel="prefetch" href="/assets/js/345.32166361.js"><link rel="prefetch" href="/assets/js/346.86ff128b.js"><link rel="prefetch" href="/assets/js/347.3c5421fe.js"><link rel="prefetch" href="/assets/js/348.95910300.js"><link rel="prefetch" href="/assets/js/349.004158d8.js"><link rel="prefetch" href="/assets/js/35.18e8f66a.js"><link rel="prefetch" href="/assets/js/350.e10b195b.js"><link rel="prefetch" href="/assets/js/351.12f89875.js"><link rel="prefetch" href="/assets/js/352.83957394.js"><link rel="prefetch" href="/assets/js/353.475971b9.js"><link rel="prefetch" href="/assets/js/354.8af7b26b.js"><link rel="prefetch" href="/assets/js/355.85925e24.js"><link rel="prefetch" href="/assets/js/356.1d77cf9c.js"><link rel="prefetch" href="/assets/js/357.b467d481.js"><link rel="prefetch" href="/assets/js/358.ac96f32d.js"><link rel="prefetch" href="/assets/js/359.e048bd10.js"><link rel="prefetch" href="/assets/js/36.a7ae257c.js"><link rel="prefetch" href="/assets/js/360.e9b45545.js"><link rel="prefetch" href="/assets/js/361.ad1bb45b.js"><link rel="prefetch" href="/assets/js/362.4e24a30b.js"><link rel="prefetch" href="/assets/js/363.64f7dad5.js"><link rel="prefetch" href="/assets/js/364.d9e3ebc2.js"><link rel="prefetch" href="/assets/js/365.330e3086.js"><link rel="prefetch" href="/assets/js/366.a6c0afb3.js"><link rel="prefetch" href="/assets/js/367.ffcefa40.js"><link rel="prefetch" href="/assets/js/368.664c8e4d.js"><link rel="prefetch" href="/assets/js/369.67da2dd2.js"><link rel="prefetch" href="/assets/js/37.d709f9a9.js"><link rel="prefetch" href="/assets/js/370.b1791970.js"><link rel="prefetch" href="/assets/js/371.743a461a.js"><link rel="prefetch" href="/assets/js/372.7703ef1b.js"><link rel="prefetch" href="/assets/js/373.17de31f6.js"><link rel="prefetch" href="/assets/js/374.e508be9e.js"><link rel="prefetch" href="/assets/js/375.6e2e9fe3.js"><link rel="prefetch" href="/assets/js/376.8ca3511a.js"><link rel="prefetch" href="/assets/js/377.bfcee39c.js"><link rel="prefetch" href="/assets/js/378.21852b78.js"><link rel="prefetch" href="/assets/js/379.9649c307.js"><link rel="prefetch" href="/assets/js/38.68ca920e.js"><link rel="prefetch" href="/assets/js/380.dadb4418.js"><link rel="prefetch" href="/assets/js/381.a03c993d.js"><link rel="prefetch" href="/assets/js/382.bb7c22c1.js"><link rel="prefetch" href="/assets/js/383.bd68b2e5.js"><link rel="prefetch" href="/assets/js/384.f6dc7457.js"><link rel="prefetch" href="/assets/js/385.14287a91.js"><link rel="prefetch" href="/assets/js/386.a6284ac2.js"><link rel="prefetch" href="/assets/js/387.c51f147a.js"><link rel="prefetch" href="/assets/js/388.06d9651e.js"><link rel="prefetch" href="/assets/js/389.2d85d927.js"><link rel="prefetch" href="/assets/js/39.de850db9.js"><link rel="prefetch" href="/assets/js/390.2397b3e0.js"><link rel="prefetch" href="/assets/js/391.8413aaaf.js"><link rel="prefetch" href="/assets/js/392.00eecaa4.js"><link rel="prefetch" href="/assets/js/393.351dd3fd.js"><link rel="prefetch" href="/assets/js/394.d2cc4a70.js"><link rel="prefetch" href="/assets/js/395.abee64bf.js"><link rel="prefetch" href="/assets/js/396.bc265e6a.js"><link rel="prefetch" href="/assets/js/397.e4a96944.js"><link rel="prefetch" href="/assets/js/398.f0d26b29.js"><link rel="prefetch" href="/assets/js/399.e77c3ddc.js"><link rel="prefetch" href="/assets/js/4.2f502b73.js"><link rel="prefetch" href="/assets/js/40.91635261.js"><link rel="prefetch" href="/assets/js/400.c7eac401.js"><link rel="prefetch" href="/assets/js/401.06092d16.js"><link rel="prefetch" href="/assets/js/402.4e08e496.js"><link rel="prefetch" href="/assets/js/403.deba4c77.js"><link rel="prefetch" href="/assets/js/404.9100e4df.js"><link rel="prefetch" href="/assets/js/405.e9f451e2.js"><link rel="prefetch" href="/assets/js/406.a0da4aa4.js"><link rel="prefetch" href="/assets/js/407.58b2b123.js"><link rel="prefetch" href="/assets/js/408.eb2cde2d.js"><link rel="prefetch" href="/assets/js/409.9041f749.js"><link rel="prefetch" href="/assets/js/41.169a3cfc.js"><link rel="prefetch" href="/assets/js/410.c12f3710.js"><link rel="prefetch" href="/assets/js/411.452cda45.js"><link rel="prefetch" href="/assets/js/412.8691317a.js"><link rel="prefetch" href="/assets/js/413.25a68f21.js"><link rel="prefetch" href="/assets/js/414.7a9699d8.js"><link rel="prefetch" href="/assets/js/415.6e8cdaff.js"><link rel="prefetch" href="/assets/js/416.e8a86529.js"><link rel="prefetch" href="/assets/js/417.28330bde.js"><link rel="prefetch" href="/assets/js/418.2fed8e17.js"><link rel="prefetch" href="/assets/js/419.773032f4.js"><link rel="prefetch" href="/assets/js/42.e17cd061.js"><link rel="prefetch" href="/assets/js/420.56681228.js"><link rel="prefetch" href="/assets/js/421.0d170e13.js"><link rel="prefetch" href="/assets/js/422.fc8c2a11.js"><link rel="prefetch" href="/assets/js/423.e34ea6a6.js"><link rel="prefetch" href="/assets/js/424.20fe8748.js"><link rel="prefetch" href="/assets/js/425.f001b7cd.js"><link rel="prefetch" href="/assets/js/426.a91230ef.js"><link rel="prefetch" href="/assets/js/427.c6c9fe8d.js"><link rel="prefetch" href="/assets/js/428.9d4f5e41.js"><link rel="prefetch" href="/assets/js/429.c81cfd3f.js"><link rel="prefetch" href="/assets/js/43.f88aa667.js"><link rel="prefetch" href="/assets/js/430.eb61372f.js"><link rel="prefetch" href="/assets/js/431.4a25365a.js"><link rel="prefetch" href="/assets/js/432.42fc1bbe.js"><link rel="prefetch" href="/assets/js/433.8e9ac9f0.js"><link rel="prefetch" href="/assets/js/434.fdd0b160.js"><link rel="prefetch" href="/assets/js/435.d6cbac31.js"><link rel="prefetch" href="/assets/js/436.17750ba2.js"><link rel="prefetch" href="/assets/js/437.a1468099.js"><link rel="prefetch" href="/assets/js/438.ac6a45c2.js"><link rel="prefetch" href="/assets/js/439.242ae27a.js"><link rel="prefetch" href="/assets/js/44.3f36e228.js"><link rel="prefetch" href="/assets/js/440.b80b520c.js"><link rel="prefetch" href="/assets/js/441.e51a4bbb.js"><link rel="prefetch" href="/assets/js/442.ab0b3eda.js"><link rel="prefetch" href="/assets/js/443.47e44250.js"><link rel="prefetch" href="/assets/js/444.54c3b425.js"><link rel="prefetch" href="/assets/js/445.e006c12e.js"><link rel="prefetch" href="/assets/js/446.f2b79730.js"><link rel="prefetch" href="/assets/js/447.2509a397.js"><link rel="prefetch" href="/assets/js/448.b7d69dfc.js"><link rel="prefetch" href="/assets/js/449.8a575d9b.js"><link rel="prefetch" href="/assets/js/45.be1455b1.js"><link rel="prefetch" href="/assets/js/450.ad421aeb.js"><link rel="prefetch" href="/assets/js/451.f09912ae.js"><link rel="prefetch" href="/assets/js/452.f528c4ce.js"><link rel="prefetch" href="/assets/js/453.fc4dc0f9.js"><link rel="prefetch" href="/assets/js/454.733c315c.js"><link rel="prefetch" href="/assets/js/455.44fe35b1.js"><link rel="prefetch" href="/assets/js/456.7f650035.js"><link rel="prefetch" href="/assets/js/457.77ebc183.js"><link rel="prefetch" href="/assets/js/458.133078f4.js"><link rel="prefetch" href="/assets/js/459.33728b5e.js"><link rel="prefetch" href="/assets/js/46.5ad74cb5.js"><link rel="prefetch" href="/assets/js/460.6946f564.js"><link rel="prefetch" href="/assets/js/461.6f906c5c.js"><link rel="prefetch" href="/assets/js/462.26eca27e.js"><link rel="prefetch" href="/assets/js/463.e02e5f65.js"><link rel="prefetch" href="/assets/js/464.0df25c63.js"><link rel="prefetch" href="/assets/js/465.80cd249e.js"><link rel="prefetch" href="/assets/js/466.a0921e86.js"><link rel="prefetch" href="/assets/js/467.1bec2b47.js"><link rel="prefetch" href="/assets/js/468.b6fa37c1.js"><link rel="prefetch" href="/assets/js/469.a1d2487e.js"><link rel="prefetch" href="/assets/js/47.03df5d0a.js"><link rel="prefetch" href="/assets/js/470.36a4b9c8.js"><link rel="prefetch" href="/assets/js/471.28895273.js"><link rel="prefetch" href="/assets/js/472.b9fe392f.js"><link rel="prefetch" href="/assets/js/473.a2835d9c.js"><link rel="prefetch" href="/assets/js/474.cd57b37d.js"><link rel="prefetch" href="/assets/js/475.8d5a9792.js"><link rel="prefetch" href="/assets/js/476.f7f3781c.js"><link rel="prefetch" href="/assets/js/477.9b710b04.js"><link rel="prefetch" href="/assets/js/478.46d66687.js"><link rel="prefetch" href="/assets/js/479.e7444705.js"><link rel="prefetch" href="/assets/js/48.48f286ba.js"><link rel="prefetch" href="/assets/js/480.da2b750a.js"><link rel="prefetch" href="/assets/js/481.838a8e04.js"><link rel="prefetch" href="/assets/js/482.02bf8041.js"><link rel="prefetch" href="/assets/js/483.bb29ef2f.js"><link rel="prefetch" href="/assets/js/484.aebb68bd.js"><link rel="prefetch" href="/assets/js/485.a66ab41b.js"><link rel="prefetch" href="/assets/js/486.8df516fb.js"><link rel="prefetch" href="/assets/js/487.86d28130.js"><link rel="prefetch" href="/assets/js/488.0863da70.js"><link rel="prefetch" href="/assets/js/489.5d4d9e88.js"><link rel="prefetch" href="/assets/js/49.1ca52d11.js"><link rel="prefetch" href="/assets/js/490.3fd65d85.js"><link rel="prefetch" href="/assets/js/491.ae3a2f87.js"><link rel="prefetch" href="/assets/js/492.6f54679b.js"><link rel="prefetch" href="/assets/js/493.a594b1f4.js"><link rel="prefetch" href="/assets/js/494.4f03fae1.js"><link rel="prefetch" href="/assets/js/495.ae50b66b.js"><link rel="prefetch" href="/assets/js/496.bc92d835.js"><link rel="prefetch" href="/assets/js/497.eac65251.js"><link rel="prefetch" href="/assets/js/498.1d726726.js"><link rel="prefetch" href="/assets/js/499.01e4f7d1.js"><link rel="prefetch" href="/assets/js/5.7b1f056c.js"><link rel="prefetch" href="/assets/js/50.73732fe2.js"><link rel="prefetch" href="/assets/js/500.062ade4e.js"><link rel="prefetch" href="/assets/js/501.e6a711dc.js"><link rel="prefetch" href="/assets/js/502.c79e28e2.js"><link rel="prefetch" href="/assets/js/503.bf97bce9.js"><link rel="prefetch" href="/assets/js/504.b2784ef0.js"><link rel="prefetch" href="/assets/js/505.0767ba54.js"><link rel="prefetch" href="/assets/js/506.8ae14637.js"><link rel="prefetch" href="/assets/js/507.003e2349.js"><link rel="prefetch" href="/assets/js/508.ecb5e6bd.js"><link rel="prefetch" href="/assets/js/509.b644f44a.js"><link rel="prefetch" href="/assets/js/51.bed7cf61.js"><link rel="prefetch" href="/assets/js/510.b660946f.js"><link rel="prefetch" href="/assets/js/511.cb186c8f.js"><link rel="prefetch" href="/assets/js/512.d176170f.js"><link rel="prefetch" href="/assets/js/513.18a1afa5.js"><link rel="prefetch" href="/assets/js/514.4a33e931.js"><link rel="prefetch" href="/assets/js/515.8496bd4d.js"><link rel="prefetch" href="/assets/js/516.529b9476.js"><link rel="prefetch" href="/assets/js/517.289738f1.js"><link rel="prefetch" href="/assets/js/518.eda39556.js"><link rel="prefetch" href="/assets/js/519.85b42de5.js"><link rel="prefetch" href="/assets/js/52.22a7da62.js"><link rel="prefetch" href="/assets/js/520.8b531775.js"><link rel="prefetch" href="/assets/js/521.8e4b66fb.js"><link rel="prefetch" href="/assets/js/522.050bfc55.js"><link rel="prefetch" href="/assets/js/523.e973f1e0.js"><link rel="prefetch" href="/assets/js/524.fd160738.js"><link rel="prefetch" href="/assets/js/525.5a4bc307.js"><link rel="prefetch" href="/assets/js/526.361bc4fa.js"><link rel="prefetch" href="/assets/js/527.06ee9d73.js"><link rel="prefetch" href="/assets/js/528.22d9b118.js"><link rel="prefetch" href="/assets/js/529.b7592c16.js"><link rel="prefetch" href="/assets/js/53.767f3bbf.js"><link rel="prefetch" href="/assets/js/530.ad96d564.js"><link rel="prefetch" href="/assets/js/531.61905243.js"><link rel="prefetch" href="/assets/js/532.11aebf61.js"><link rel="prefetch" href="/assets/js/533.0cddb226.js"><link rel="prefetch" href="/assets/js/534.d1c9cc36.js"><link rel="prefetch" href="/assets/js/54.d1f9eec8.js"><link rel="prefetch" href="/assets/js/55.aa90e812.js"><link rel="prefetch" href="/assets/js/56.4d7f81f2.js"><link rel="prefetch" href="/assets/js/57.3c540e8d.js"><link rel="prefetch" href="/assets/js/58.fc1c23f2.js"><link rel="prefetch" href="/assets/js/59.c7a7a4c0.js"><link rel="prefetch" href="/assets/js/6.056886f1.js"><link rel="prefetch" href="/assets/js/60.40e590ae.js"><link rel="prefetch" href="/assets/js/61.e400b323.js"><link rel="prefetch" href="/assets/js/62.bbb30ef1.js"><link rel="prefetch" href="/assets/js/63.c31cd2bb.js"><link rel="prefetch" href="/assets/js/64.62321188.js"><link rel="prefetch" href="/assets/js/65.44adc2b3.js"><link rel="prefetch" href="/assets/js/66.b5740d4f.js"><link rel="prefetch" href="/assets/js/67.76c3624c.js"><link rel="prefetch" href="/assets/js/68.6dd982d4.js"><link rel="prefetch" href="/assets/js/69.eb1390ec.js"><link rel="prefetch" href="/assets/js/7.a96cecf9.js"><link rel="prefetch" href="/assets/js/70.8c882bdd.js"><link rel="prefetch" href="/assets/js/71.001c968a.js"><link rel="prefetch" href="/assets/js/72.ae4ca075.js"><link rel="prefetch" href="/assets/js/73.d6ae6a27.js"><link rel="prefetch" href="/assets/js/74.fba60e37.js"><link rel="prefetch" href="/assets/js/75.0b1bf7bf.js"><link rel="prefetch" href="/assets/js/76.ee19d90e.js"><link rel="prefetch" href="/assets/js/77.fe8ac5f0.js"><link rel="prefetch" href="/assets/js/78.ae09432e.js"><link rel="prefetch" href="/assets/js/79.c1b10e2d.js"><link rel="prefetch" href="/assets/js/80.ae809538.js"><link rel="prefetch" href="/assets/js/81.ca11b4c7.js"><link rel="prefetch" href="/assets/js/82.308b98e4.js"><link rel="prefetch" href="/assets/js/83.355d9dde.js"><link rel="prefetch" href="/assets/js/84.a2b61d48.js"><link rel="prefetch" href="/assets/js/85.cf992fda.js"><link rel="prefetch" href="/assets/js/86.f547c7ea.js"><link rel="prefetch" href="/assets/js/87.2b02746a.js"><link rel="prefetch" href="/assets/js/88.e939aad5.js"><link rel="prefetch" href="/assets/js/89.b000c42a.js"><link rel="prefetch" href="/assets/js/90.dadef001.js"><link rel="prefetch" href="/assets/js/91.c0fe2e32.js"><link rel="prefetch" href="/assets/js/92.e09650b9.js"><link rel="prefetch" href="/assets/js/93.427c7280.js"><link rel="prefetch" href="/assets/js/94.90fc5f58.js"><link rel="prefetch" href="/assets/js/95.13d42b3a.js"><link rel="prefetch" href="/assets/js/96.d0a2ea8c.js"><link rel="prefetch" href="/assets/js/97.cc9a0eda.js"><link rel="prefetch" href="/assets/js/98.3c9f1b7e.js"><link rel="prefetch" href="/assets/js/99.0420dcbc.js"><link rel="prefetch" href="/assets/js/vendors~docsearch.33b2b47d.js">
    <link rel="stylesheet" href="/assets/css/0.styles.40c15e22.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/logo.png" alt="鱼皮的编程宝典" class="logo"> <span class="site-name can-hide">鱼皮的编程宝典</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/学习路线/" class="nav-link">
  学习路线
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="自学之路" class="dropdown-title"><span class="title">自学之路</span> <span class="arrow down"></span></button> <button type="button" aria-label="自学之路" class="mobile-dropdown-title"><span class="title">自学之路</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/自学之路/#大学经历" class="nav-link">
  大学经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#求职经历" class="nav-link">
  求职经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#职场工作" class="nav-link">
  职场工作
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#创作经历" class="nav-link">
  创作经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#创业经历" class="nav-link">
  创业经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#生活日常" class="nav-link">
  生活日常
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="编程分享" class="dropdown-title"><span class="title">编程分享</span> <span class="arrow down"></span></button> <button type="button" aria-label="编程分享" class="mobile-dropdown-title"><span class="title">编程分享</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/编程分享/#入门必看-学习路线" class="nav-link">
  入门必看-学习路线
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#学习指南" class="nav-link">
  学习指南
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#开发经验" class="nav-link">
  开发经验
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#求职经验" class="nav-link">
  求职经验
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#职场经验" class="nav-link">
  职场经验
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#技术分享" class="nav-link">
  技术分享
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#实战教程" class="nav-link">
  实战教程
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#其他" class="nav-link">
  其他
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#📚-项目教程" class="nav-link">
  项目教程
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#个人作品" class="nav-link">
  个人作品
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#🎁-编程资源" class="nav-link">
  编程资源
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#🌐-科技科普" class="nav-link">
  科技科普
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="项目实战" class="dropdown-title"><span class="title">项目实战</span> <span class="arrow down"></span></button> <button type="button" aria-label="项目实战" class="mobile-dropdown-title"><span class="title">项目实战</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/项目实战/OJ 判题系统.html" class="nav-link">
  OJ 判题系统
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/智能 BI 平台.html" class="nav-link">
  智能 BI 平台
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/聚合搜索平台.html" class="nav-link">
  聚合搜索平台
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/API 开放平台.html" class="nav-link">
  API 开放平台
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/伙伴匹配系统.html" class="nav-link">
  伙伴匹配系统
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/用户中心项目.html" class="nav-link">
  用户中心项目
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/Java 后端万用项目模板.html" class="nav-link">
  Java 后端万用项目模板
</a></li></ul></div></div><div class="nav-item"><a href="/知识碎片/" class="nav-link">
  知识碎片
</a></div><div class="nav-item"><a href="/编程导航/" class="nav-link">
  🔥 编程导航
</a></div><div class="nav-item"><a href="/产品服务/" class="nav-link">
  产品服务
</a></div><div class="nav-item"><a href="/作者/" class="nav-link">
  作者
</a></div> <a href="https://github.com/liyupi/codefather" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/学习路线/" class="nav-link">
  学习路线
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="自学之路" class="dropdown-title"><span class="title">自学之路</span> <span class="arrow down"></span></button> <button type="button" aria-label="自学之路" class="mobile-dropdown-title"><span class="title">自学之路</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/自学之路/#大学经历" class="nav-link">
  大学经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#求职经历" class="nav-link">
  求职经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#职场工作" class="nav-link">
  职场工作
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#创作经历" class="nav-link">
  创作经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#创业经历" class="nav-link">
  创业经历
</a></li><li class="dropdown-item"><!----> <a href="/自学之路/#生活日常" class="nav-link">
  生活日常
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="编程分享" class="dropdown-title"><span class="title">编程分享</span> <span class="arrow down"></span></button> <button type="button" aria-label="编程分享" class="mobile-dropdown-title"><span class="title">编程分享</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/编程分享/#入门必看-学习路线" class="nav-link">
  入门必看-学习路线
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#学习指南" class="nav-link">
  学习指南
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#开发经验" class="nav-link">
  开发经验
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#求职经验" class="nav-link">
  求职经验
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#职场经验" class="nav-link">
  职场经验
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#技术分享" class="nav-link">
  技术分享
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#实战教程" class="nav-link">
  实战教程
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#其他" class="nav-link">
  其他
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#📚-项目教程" class="nav-link">
  项目教程
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#个人作品" class="nav-link">
  个人作品
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#🎁-编程资源" class="nav-link">
  编程资源
</a></li><li class="dropdown-item"><!----> <a href="/编程分享/#🌐-科技科普" class="nav-link">
  科技科普
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="项目实战" class="dropdown-title"><span class="title">项目实战</span> <span class="arrow down"></span></button> <button type="button" aria-label="项目实战" class="mobile-dropdown-title"><span class="title">项目实战</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/项目实战/OJ 判题系统.html" class="nav-link">
  OJ 判题系统
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/智能 BI 平台.html" class="nav-link">
  智能 BI 平台
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/聚合搜索平台.html" class="nav-link">
  聚合搜索平台
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/API 开放平台.html" class="nav-link">
  API 开放平台
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/伙伴匹配系统.html" class="nav-link">
  伙伴匹配系统
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/用户中心项目.html" class="nav-link">
  用户中心项目
</a></li><li class="dropdown-item"><!----> <a href="/项目实战/Java 后端万用项目模板.html" class="nav-link">
  Java 后端万用项目模板
</a></li></ul></div></div><div class="nav-item"><a href="/知识碎片/" class="nav-link">
  知识碎片
</a></div><div class="nav-item"><a href="/编程导航/" class="nav-link">
  🔥 编程导航
</a></div><div class="nav-item"><a href="/产品服务/" class="nav-link">
  产品服务
</a></div><div class="nav-item"><a href="/作者/" class="nav-link">
  作者
</a></div> <a href="https://github.com/liyupi/codefather" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><a href="/%E7%BC%96%E7%A8%8B%E5%88%86%E4%BA%AB/" class="sidebar-link">入门必看 - 学习路线</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>入门必看-学习路线</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>学习指南</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>开发经验</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>求职经验</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>职场经验</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>技术分享</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>实战教程</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>项目教程</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>编程资源</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>科技科普</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>其他</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="content"><div style="width:100%"><div class="theme-default-content custom-content content__default"><h1 id="尝鲜-svelte-前端框架-开发读书笔记"><a href="#尝鲜-svelte-前端框架-开发读书笔记" class="header-anchor">#</a> 尝鲜 Svelte 前端框架，开发读书笔记</h1> <blockquote><p>本文作者：<a href="https://yuyuanweb.feishu.cn/wiki/Abldw5WkjidySxkKxU2cQdAtnah" target="_blank" rel="noopener noreferrer">程序员鱼皮<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p>本站地址：<a href="https://codefather.cn" target="_blank" rel="noopener noreferrer">https://codefather.cn<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p></blockquote> <p>提到前端开发框架，我相信大家第一时间想到的就是 Vue、React 和 Angular 三大主流。毕竟它们各个都是 GitHub 上 10w+ star 的知名项目，每个前端工程师至少要学习其中一个框架。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010202.png" loading="lazy" class="lazy"></p> <p>但是，最近几年，一个新的前端框架逐渐出现在人们眼前，它就是后起之秀『 Svelte 』。目前已经接近 4w 个 star，虽然暂时无法撼动三大主流框架的霸主地位，但是其恐怖的 star 增速，值得我们关注和思考。</p> <p>Svelte 到底是什么样的框架？它和三大主流框架有什么不同？为什么发展如此迅猛？</p> <p>带着这些问题，我们一起来学习下 Svelte 框架，并用它从 0 到 1，开发一个读书笔记小网站。</p> <p>可以先通过一分钟的小视频简单地了解下 Svelte ~</p> <p>，时长00:46</p> <h3 id=""><a href="#" class="header-anchor">#</a></h3> <h3 id="揭开-svelte-的神秘面纱"><a href="#揭开-svelte-的神秘面纱" class="header-anchor">#</a> 揭开 Svelte 的神秘面纱</h3> <p>按照官网的描述，Svelte 是一种构建用户界面的框架，框架自身具有反应性，可以帮助开发者书写更精简的代码，开发出体积更小、更迅速的 App。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010441.png" loading="lazy" class="lazy"></p> <p>使用 Svelte 框架进行开发，需要遵循其特定的语法，编写 <code>.svelte</code> 后缀的文件。如下是 Svelte 框架的 <code>Hello World</code> 代码：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010097.png" loading="lazy" class="lazy"></p> <p>你可能会质疑：这不就和 Vue、React 之类的前端框架一样么？不就是用个数据绑定、抄个 API 和语法风格、改个文件后缀名么？凭什么能获得 4w 的 star？</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010067.png" loading="lazy" class="lazy"></p> <p>其实，近几年出现的新前端框架并不少，但都被遮挡在了三座大山下，没有一个能够像 Svelte 一样在短期内得到大量的关注。</p> <p>究竟是什么让 Svelte 框架破圈突围，剑指 Angular ？</p> <h3 id="svelte-新在哪儿"><a href="#svelte-新在哪儿" class="header-anchor">#</a> Svelte 新在哪儿？</h3> <p>我们先来看两张图，是对 20 多种前端框架 Demo 项目的性能对比和评测。</p> <p>第一张图是对比各框架开发的项目的<strong>尺寸</strong>：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010453.png" loading="lazy" class="lazy"></p> <p>第二张图是对比各项目的 Lighthouse 性能评分：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010947.jpeg" loading="lazy" class="lazy"></p> <p>从上面两张图，我们发现，Svelte 框架无论是在项目尺寸还是性能方面，都表现卓越。一个用 Svelte 开发的 Demo 项目竟然仅有 15 KB！怎么会这么小呢？有黑魔法？</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010448.png" loading="lazy" class="lazy"></p> <p>这和 Svelte 独特的设计思想有关。基本所有传统的前端框架，在项目运行时都会依赖框架本身的代码，即引入了框架作为 runtime（运行时），因此需要将框架代码打进项目包，占用了一定的包大小。</p> <p>比如 Vue 项目的包管理文件 <code>package.json</code> 中，将 Vue 作为生产环境运行时依赖引入。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&quot;dependencies&quot;: {
  &quot;vue&quot;: &quot;^2.6.11&quot;
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>而 Svelte 框架的核心思想在于『 通过静态编译减少框架运行时的代码量 』（尤雨溪大佬的解释）。</p> <p>Svelte 不会将自己打包进项目，而是在编译打包阶段，将 Svelte 组件转换为原生 DOM 操作。因此，使用 Svelte 开发的项目，并不依赖 runtime，更没有像 Vue 和 React 中的 Virtual DOM，项目的体积也非常地小。</p> <p>下面是 Svelte 项目的 <code>package.json</code> 文件，可以发现，svelte 是被作为开发时依赖引入。</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&quot;devDependencies&quot;: {
  &quot;svelte&quot;: &quot;^3.0.0&quot;
}
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>这是 Svelte 和其他前端框架的明显区别。与其说是 “新”，倒不如说是回归原始，返璞归真。</p> <p>除了不依赖 runtime 和 Virtual DOM 外，Svelte 另一个 “新” 体现在其自身具有<strong>反应性</strong>，可以轻松地实现状态管理，而无需像 Vue 和 React 框架一样引入 Vuex 和 Redux 之类的状态管理库。这一点给开发者提供了极大地便利。</p> <p>了解了 Svelte 框架的独特之处，让我们趁热打铁，做一个小项目来感受使用 Svelte 进行开发的高效和乐趣~</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010567.jpeg" loading="lazy" class="lazy"></p> <h3 id="十分钟开发读书笔记"><a href="#十分钟开发读书笔记" class="header-anchor">#</a> 十分钟开发读书笔记</h3> <p>接下来，我们要开发一个读书笔记，来记录自己每日的学习内容。</p> <p>先分析下需求，读书笔记需要有如下基本功能：</p> <ol><li>添加读书笔记</li> <li>展示已添加的读书笔记</li> <li>删除某一条读书笔记</li> <li>导出读书笔记成 Markdown 格式的文件，并下载至本地</li></ol> <p><strong>成品效果如下：</strong></p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010922.gif" loading="lazy" class="lazy"></p> <p>体验地址：https://read-note.now.sh/</p> <p>总共分为四步，顺利的话，只用十分钟就可以开发完成并部署上线~</p> <h4 id="_1-启动模板项目"><a href="#_1-启动模板项目" class="header-anchor">#</a> 1. 启动模板项目</h4> <p>可以通过以下两种方式下载 Svelte 的模板项目。</p> <p><strong>方式一</strong></p> <p>直接下载压缩包，并手动解压，地址：https://github.com/sveltejs/template/archive/master.zip</p> <p><strong>方式二</strong></p> <p>通过 npx 命令创建一个 Svelte 模板项目：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>npx degit sveltejs/template svelte-app
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>下载模板到本地后，进入项目目录，输入命令安装依赖：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>npm install
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>Svelte 框架使用 Rollup 作为 JS 模块打包工具（也是大佬写的轮子），依赖安装完成后，通过控制台输入命令，在本地启动项目：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>npm run dev
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>控制台看到如下输出，项目启动成功：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010565.png" loading="lazy" class="lazy"></p> <p>浏览器访问 localhost:5000，可以看到如下界面：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010651.png" loading="lazy" class="lazy"></p> <h4 id="_2-开发界面"><a href="#_2-开发界面" class="header-anchor">#</a> 2. 开发界面</h4> <p>完成项目模板的下载和启动后，开始进入读书笔记界面的开发。</p> <p>读书笔记只有一个主页面，先观察页面的布局，分为上下两部分，上方是一张张相同样式卡片组成的列表，下方是操作面板：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010919.png" loading="lazy" class="lazy"></p> <p>因此，我们只需要开发两个组件，<strong>卡片</strong> 和 <strong>操作面板</strong>。然后将多张卡片组成列表放在主页面上方，操作面板固定在主页面底部。</p> <p>在项目 src 目录下新建几个 <code>.svelte</code> 文件（Svelte 框架的页面文件，<code>App.svelte</code> 为模板自带的主页面），此时目录结构如下：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010918.png" loading="lazy" class="lazy"></p> <p><code>.svelte</code> 文件的语法结构和 Vue 框架非常类似，由行为、页面、样式三部分组成，分别对应 JavaScript、HTML、CSS 代码。一个标准的 <code>.svelte</code> 文件代码如下：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
 // 编写网页交互行为
&lt;/script&gt;

&lt;div&gt;
 &lt;!-- 编写页面内容结构 --&gt;
&lt;/div&gt;

&lt;style&gt;
 /* 编写 CSS 样式 */
&lt;/style&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><h5 id="-2"><a href="#-2" class="header-anchor">#</a></h5> <h5 id="-3"><a href="#-3" class="header-anchor">#</a></h5> <h5 id="_2-1-开发卡片组件"><a href="#_2-1-开发卡片组件" class="header-anchor">#</a> 2.1 开发卡片组件</h5> <p>读书笔记的每张卡片都要有标题、内容和创建日期，还要给卡片编号，并给不同编号的卡片加上不同的颜色。当鼠标移到卡片上时，出现删除按钮。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010762.png" loading="lazy" class="lazy"></p> <p>打开 <code>Card.svelte</code> 文件，先在 <code>script</code> 标签中用 JavaScript 定义几个属性变量（组件内唯一）和一个删除函数：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  // 定义变量
  export let title; // 标题
  export let content; // 内容
  export let creationTime; // 创建日期
  export let index = 0; // 卡片序号
  
  // 删除卡片
  function doDelete() { }
&lt;/script&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>然后编写卡片的内容，先用一个根 <code>div</code> 标签括起所有的内容，然后编写标题、内容、创建时间的 <code>div</code> 标签。在 Svelte 中，可以直接使用尖括号来输出变量的值，使用 <code>on:click</code> 指令来绑定鼠标点击事件：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;div class={`card bg-color-${index % 5}`}&gt;
  &lt;div class=&quot;title&quot;&gt;
    {title} &lt;span class=&quot;del-btn&quot; on:click={doDelete}&gt;x&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class=&quot;content&quot;&gt;{content}&lt;/div&gt;
  &lt;div class=&quot;creationTime&quot;&gt;{creationTime}&lt;/div&gt;
&lt;/div&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>在 <code>style</code> 标签中编写 CSS 代码，让卡片变得美美哒：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;style&gt;
  .card {
    padding: 1rem;
    margin: 1rem;
    color: #fff;
    border-radius: 0.5rem;
  }
  
  /* 省略... */
  
  /* 当鼠标移到卡片上，展示删除按钮 */
  .card:hover .del-btn {
    opacity: 1;
  }
&lt;/style&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h5 id="-4"><a href="#-4" class="header-anchor">#</a></h5> <h5 id="-5"><a href="#-5" class="header-anchor">#</a></h5> <h5 id="_2-2-开发操作面板组件"><a href="#_2-2-开发操作面板组件" class="header-anchor">#</a> 2.2 开发操作面板组件</h5> <p>操作面板包含两个输入框和两个按钮，用于添加卡片和导出笔记。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010460.png" loading="lazy" class="lazy"></p> <p>打开 <code>AddCard.svelte</code> 文件，和开发卡片一样，先编写 JavaScript，定义几个属性变量，以及 “添加” 和 “导出” 函数：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  // 在 src 目录下新建 utils 工具类，编写获取当前日期的函数
  import {getNowDateFormat} from &quot;./utils&quot;;

  // 定义变量
  let title = ''; // 标题
  let content = ''; // 内容

  // 添加卡片
  function doAdd() { }

  // 导出笔记
  function doExport() { }
&lt;/script&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><p>然后编写操作面板的内容，Svelte 通过 <code>bind:value</code> 指令实现表单数据的双向绑定：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;div class=&quot;add-card&quot;&gt;
  &lt;div class=&quot;input-wrapper&quot;&gt;
    &lt;input class=&quot;input-title&quot; type=&quot;text&quot; placeholder=&quot;输入标题&quot; bind:value={title} /&gt;
    &lt;textarea class=&quot;input-content&quot; placeholder=&quot;输入内容&quot; bind:value={content}&gt;&lt;/textarea&gt;
  &lt;/div&gt;
  &lt;button class=&quot;add-btn&quot; on:click={doAdd}&gt;添加&lt;/button&gt;
  &lt;button class=&quot;export-btn&quot; on:click={doExport}&gt;导出&lt;/button&gt;
&lt;/div&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>最后编写 CSS 代码，让操作面板变得美美哒~ 此处使用 Flex 布局：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;style&gt;
  /* 操作面板固定在页面底部 */
  .add-card {
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    box-sizing: border-box;
    padding: 1rem;
    background-image: linear-gradient(135deg, #FEC163 10%, #DE4313 100%);
    display: flex;
  }

  .input-wrapper {
    flex: 4; /* 使用 Flex 布局 */
  }

  /* 省略... */
  
  .add-btn, .export-btn {
    flex: 1;
    margin-left: 1rem;
    color: #666;
  }
&lt;/style&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><h5 id="-6"><a href="#-6" class="header-anchor">#</a></h5> <h5 id="-7"><a href="#-7" class="header-anchor">#</a></h5> <h5 id="_2-3-将组件放入主页面"><a href="#_2-3-将组件放入主页面" class="header-anchor">#</a> 2.3 将组件放入主页面</h5> <p>开发完卡片和操作面板组件后，只需要将这些组件丢到 Svelte 模板项目默认生成的主页面 <code>App.svelte</code> 中，在 <code>script</code> 标签中通过 <code>import</code> 关键字引入组件：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  import Card from &quot;./Card.svelte&quot;;
  import AddCard from &quot;./AddCard.svelte&quot;;
&lt;/script&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>在 div 标签中，通过 <code>{# each ... } {/each}</code> 循环语句实现卡片列表，直接通过组件名引入组件：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;div id=&quot;app&quot;&gt;
  {#each $cards as card, i}
    &lt;Card {...card} index={i}/&gt;
  {/each}
  &lt;AddCard/&gt;
&lt;/div&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>细心的小伙伴可能会好奇，上述代码第 2 行的 <code>$cards</code> 变量是从哪儿来的呢？不着急，稍后揭晓~</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010966.jpeg" loading="lazy" class="lazy"></p> <p>大功告成！读书笔记的界面开发好了，但这时，所有的按钮都没有任何作用，下面我们来给读书笔记添加功能。</p> <h4 id="_3-实现功能"><a href="#_3-实现功能" class="header-anchor">#</a> 3. 实现功能</h4> <p>不知道大家有没有发现，我们要做的读书笔记，其实就是个简单的增删改查项目！</p> <p>既然是增删改查，那肯定要有地方存储数据，记录数据的变化。通常数据是存在数据库中的，通过向后端发出请求来操作和查询数据库中的数据。</p> <p>但这里我们只是一个前端项目，没有数据库，怎么办呢？可以直接使用 Svelte 自带的状态管理 API 来实现本地数据管理，无需引入任何新的依赖！</p> <h5 id="_3-1-管理卡片数据"><a href="#_3-1-管理卡片数据" class="header-anchor">#</a> 3.1 管理卡片数据</h5> <p>在项目 src 目录下新建 <code>store.js</code>，作为数据管理文件，此时目录结构如下：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010194.png" loading="lazy" class="lazy"></p> <p>在 <code>store.js</code> 文件中通过 <code>writable</code> 函数定义 <code>cards</code> 可写变量：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>import {writable} from &quot;svelte/store&quot;;

export const cards = writable([]);
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>定义好之后，<code>cards</code> 已经被 Svelte 框架管理了，可以直接把 <code>cards</code> 当做一个全局变量来使用。</p> <p>在主页面中引入 <code>cards</code>，并通过循环语句展示已添加的卡片列表。注意，想要使用状态变量，要在变量名前添加 <code>$</code> 符号。此时的主页面文件  <code>App.svelte</code> 内容如下：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  import {cards} from './store'; // 引入 cards
  import Card from &quot;./Card.svelte&quot;;
  import AddCard from &quot;./AddCard.svelte&quot;;
&lt;/script&gt;

&lt;div id=&quot;app&quot;&gt;
  {#each $cards as card, i}
    &lt;Card {...card} index={i}/&gt;
  {/each}
  &lt;AddCard/&gt;
&lt;/div&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>完成了 <code>cards</code> 的展示后，我们依次实现 <code>cards</code> 的添加和删除吧~</p> <h5 id="_3-2-添加卡片"><a href="#_3-2-添加卡片" class="header-anchor">#</a> 3.2 添加卡片</h5> <p>点击操作面板的添加按钮，可以添加卡片。须实现 <code>AddCard.svelte</code> 文件的添加函数：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  // 引入状态
  import {cards} from './store';
  import {getNowDateFormat} from &quot;./utils&quot;;

  let title = '';
  let content = '';

  function doAdd() {
    // 校验
    if (!title || !content) {
      alert('标题和内容必须都填！');
      return;
    }
    
    // 更新卡片状态，追加一个新卡片
    cards.update(item =&gt; {
      item = [...item, {
        title,
        content,
        creationTime: getNowDateFormat()
      }];
      return item;
    })
  }
&lt;/script&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>上述文件第 15 行起，通过调用 <code>cards</code> 状态变量的 <code>update</code> 函数，在原数组后追加一个元素，实现新增卡片。</p> <h5 id="_3-3-删除卡片"><a href="#_3-3-删除卡片" class="header-anchor">#</a> 3.3 删除卡片</h5> <p>点击卡片上的删除按钮，可以删除当前卡片。须实现 <code>Card.svelte</code> 文件的删除函数：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  import {cards} from &quot;./store&quot;;
 
  // 删除卡片
  function doDelete() {
    cards.update(item =&gt; {
      item.splice(index, 1);
      return item;
    })
  }
&lt;/script&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>删除卡片和添加卡片操作类似，都是调用 <code>cards</code> 状态变量的 <code>update</code> 函数，对原数组进行处理，并使用处理后的数组进行更新。</p> <h5 id="_3-4-导出笔记"><a href="#_3-4-导出笔记" class="header-anchor">#</a> 3.4 导出笔记</h5> <p>点击操作面板上的导出按钮，将已添加的卡片导出为 Markdown 格式的笔记文件，实现比较简单。</p> <p>首先安装 <code>file-saver</code> 库，依赖这个库实现下载功能：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>npm i file-saver
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>实现 <code>AddCard.svelte</code> 文件中的导出函数，将 <code>cards</code> 状态数组保存为文件：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>&lt;script&gt;
  import {cards} from './store';
  // 引入 file-saver
  import {saveAs} from 'file-saver';
  
 // 导出为 read_note.md 文件
  function doExport() {
    const texts = [];
    // 读取 cards 状态数组
    for (const card of $cards) {
      let text = `### ${card.title}\n${card.content}\n${card.creationTime}\n`;
      texts.push(text);
    }
    // 写入文件
    const blob = new Blob(texts, {type: &quot;text/plain;charset=utf-8&quot;});
    saveAs(blob, &quot;read_note.md&quot;);
  }
&lt;/script&gt;
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p>大功告成！一个精美的读书笔记就开发完成啦！</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010111.jpeg" loading="lazy" class="lazy"></p> <h5 id="_3-5-改进"><a href="#_3-5-改进" class="header-anchor">#</a> 3.5 改进</h5> <p>到目前为止，我们只实现了读书笔记最基本的功能，但这个笔记还存在很多问题：</p> <ol><li>其实目前我们还没有给卡片添加不同的颜色，大家可以在项目中的 <code>public/global.css</code> 文件添加颜色样式。</li> <li>关掉网页后，已经添加的卡片会消失，可以通过浏览器的 Cookie 实现持久化存储，卡片更新时，保存到 Cookie 中，再次打开网站时，从 Cookie 恢复卡片数据，并保存为状态。</li></ol> <p>感兴趣的读者可以试着实现上述改进功能，还可以发挥自己的想象，给读书笔记添加新功能哦~</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010786.jpeg" loading="lazy" class="lazy"></p> <h4 id="_4-发布上线"><a href="#_4-发布上线" class="header-anchor">#</a> 4. 发布上线</h4> <p>本地开发完成后，怎么将网站发布，让所有人都能看到呢？</p> <p>首先通过命令打包项目：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>npm run build
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>会在 <code>public</code> 目录下生成 <code>bundle.js</code> 文件：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010182.png" loading="lazy" class="lazy"></p> <p>此时的 <code>public</code> 目录结构如下：</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010181.png" loading="lazy" class="lazy"></p> <p>怎么发布网站到线上呢？先买台服务器？</p> <p>大可不必，可以使用 <strong>Vercel</strong>。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010704.png" loading="lazy" class="lazy"></p> <p>Vercel 是免费网站托管平台，可以帮我们部署网站，并生成可访问的网址。先通过 npm 安装 Vercel：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>npm install -g vercel
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>安装完成后，进入 <code>public</code> 目录，通过 <code>vercel</code> 命令发布网站：</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>cd public
vercel deploy --name read-note
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>发布成功，会得到一个网址，打开就能看到精美的读书笔记网站啦！</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010947.png" loading="lazy" class="lazy"></p> <p>在网站中启用开发者工具（按 <code>F12</code>），能够看到网页文件的加载信息，发现整个读书笔记网站大小才 <strong>16 KB</strong>！</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010301.png" loading="lazy" class="lazy"></p> <p>简直不讲武德啊！</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010175.jpeg" loading="lazy" class="lazy"></p> <h3 id="亿点看法"><a href="#亿点看法" class="header-anchor">#</a> 亿点看法</h3> <p>翻阅了一些论坛，发现大家对于 Svelte 框架的看法褒贬不一。</p> <p>有的朋友认为 Svelte 为了减少几十 KB 的体积，而放弃了原本的 runtime 设计和完善的生态，得不偿失。毕竟随着网络和多媒体的发展，如今一张图片的大小都要几百 KB 了，一个页面可能好几 MB，还有必要纠结那点大小么？</p> <p>也有的朋友认为 Svelte 的强大之处正是在于没有使用 runtime，可以像原生 JS 一样融合进任何框架和组件，非常适合微前端架构。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010202.jpeg" loading="lazy" class="lazy"></p> <p>我觉得，姑且不论 Svelte 现在的生态怎么样、有没有人用，首先作者这种打破思维定式、返璞归真的勇气和探索精神值得我们肯定和学习。</p> <p><strong>脱离业务场景的技术选型都是耍流氓</strong>，也许在某些配置较低、网络较差的小设备中，减小几十 KB 的包大小真的很有必要！这时，我们可能会摒弃那些重量级的框架，重回原生的怀抱。</p> <p>Svelte 框架在保证高效极简开发体验的同时，保留了原生项目的轻小体积和高性能，这是能够吸引开发者的爽点。只是目前，Svelte 这种无 Virtual DOM 的设计在生产项目中究竟能发挥多大的优势、在大型应用中的性能到底如何，还有待观察，需要更多的打磨和企业的实际检验。</p> <p>相信未来，Svelte 的开发者、建设者和布道者会越来越多，未来可期！</p> <p><strong>毕竟，多一种技术选型何乐而不为呢？</strong></p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010862.gif" loading="lazy" class="lazy"></p> <p>如果想要进一步学习 Svelte，推荐直接使用官方提供的学习教程，简洁清晰、容易上手，还能使用在线编辑器进行实时练习和调试。</p> <p><img alt="" data-src="https://pic.yupi.icu/5563/202311081010401.png" loading="lazy" class="lazy"></p> <p><strong>点击下方阅读原文一键传送</strong> 至 Svelte 官方学习教程哦~</p></div> <footer class="page-edit" style="margin:0;"><div class="edit-link"><a href="https://github.com/liyupi/codefather/edit/master/编程分享/实战教程/尝鲜 Svelte 前端框架，开发读书笔记.md" target="_blank" rel="noopener noreferrer">完善页面</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">最近更新:</span> <span class="time">11/11/2023, 8:17:47 PM</span></div></footer> <!----></div> <div class="toc-container-sidebar"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="max-height:86vh"><div style="font-weight:bold;">尝鲜 Svelte 前端框架，开发读书笔记</div> <hr> <div class="toc-box"><!----></div></div></div></div></div>  <main class="footer"> <div class="copy-right"><span class="name"> 编程导航   |     </span> <a target="_blank" rel="noreferrer">
          
        </a></div></main></main> <aside class="page-sidebar"> <div class="page-side-toolbar"></div>  </aside></div><div class="global-ui"><!----></div></div>
    <script src="/assets/js/app.12ab4756.js" defer></script><script src="/assets/js/2.fd06b53e.js" defer></script><script src="/assets/js/200.52f08765.js" defer></script>
  </body>
</html>
